package jnpf.database.source;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.handler.TableNameHandler;
import jnpf.database.constant.DbConst;
import jnpf.database.enums.datatype.DataTypeEnum;
import jnpf.database.model.DataTypeModel;
import jnpf.database.model.DbTableFieldModel;
import jnpf.database.model.DbTableModel;
import jnpf.database.source.impl.*;
import jnpf.database.sql.SqlBase;
import jnpf.database.util.DataSourceUtil;
import jnpf.database.util.JdbcUtil;
import jnpf.exception.DataException;
import lombok.Data;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;

/**
 * 数据库基础模型表
 *
 * @author JNPF开发平台组
 * @version V3.2.0
 * @copyright 引迈信息技术有限公司
 * @date 2021/6/21
 */
@Data
public abstract class DbBase {
    protected String dbEncode;
    protected String connUrlEncode;
    protected String driver;


    protected DbType mpDbType;
    public static final DbBase[] DB_BASES = {new DbMySQL(), new DbSQLServer(), new DbDM(), new DbOracle(),
            new DbKingbase(), new DbPostgre()};
    public static final String[] DB_ENCODES = {DbMySQL.DB_ENCODE, DbOracle.DB_ENCODE, DbSQLServer.DB_ENCODE,
            DbDM.DB_ENCODE, DbKingbase.DB_ENCODE, DbPostgre.DB_ENCODE};

    public DbBase() {
        setDbType();
    }

    /**
     * 设置数据库一些静态参数
     * 赋值继承父类的属性
     */
    protected abstract void setDbType();

    /**
     * 获取SQL基础模型
     *
     * @return Sql基础模型类型
     */
    public abstract SqlBase getSqlBase();

    /**
     * 获取数据类型
     *
     * @param dte 数据类型枚举
     * @return 数据类型code
     */
    public abstract DataTypeModel getDataTypeModel(DataTypeEnum dte);

    /**
     * 获取数据库字段类型模型 通过view字段类型
     *
     * @param dbFieldType 数据库字段类型模型
     */
    public abstract DataTypeModel getDataTypeModel(String dbFieldType);

    /**==================================数据源==================================**/
    /**
     * 获取数据库连接Url   关键参数：
     * 1、地址
     * 2、端口
     * 3、数据库名
     * 4、模式 （参数：?currentSchema = schema）
     * 5、jdbc-url自定义参数
     *
     * @return String 连接
     */
    public String getConnUrl(String prepareUrl, String host, Integer port, String dbName) {
        return prepareUrl.replace(DbConst.HOST, host)
                .replace(DbConst.PORT, port.toString())
                .replace(DbConst.DB_NAME, dbName);
    }

    /**
     * 动态设置数据源
     *
     * @param map          数据源map
     * @param dbTableModel 表模型
     */
    public abstract void setDynamicMap(HashMap<String, TableNameHandler> map, DbTableModel dbTableModel);

    /**=====================================模型======================================**/

    /**
     * 获取字段信息
     *
     * @param result 结果集
     * @return 表字段模型
     */
    public abstract DbTableFieldModel getFieldModel(ResultSet result) throws SQLException, DataException;

    /**
     * 获取数据库时间
     *
     * @param conn 数据连接
     * @return 时间
     */
    public abstract String getDbTime(Connection conn);

    public String dbTimeCommon(Connection conn, StringBuilder sql) {
        try {
            return JdbcUtil.queryOne(conn, sql.toString()).get("TIME").toString();
        } catch (DataException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 不同数据库结构性替换SQL语句
     *
     * @param sql              SQL语句
     * @param table            表
     * @param dbSourceOrDbLink 数据源或连接
     * @return 转换后SQL语句
     */
    public abstract String getReplaceSql(String sql, String table, DataSourceUtil dbSourceOrDbLink);


}
